﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data.Linq;

namespace DataAccesLayer
{
    public class DocumentDataAccesLayer  
    {
        eQualDataContext  provider = EQualDataProvider.EQualDataContext;

        System.Data.Linq.Table<Document> _documents;

        Func<Document, Document, bool> documentEqualityCondition = delegate(Document doc1, Document doc2) { return doc1.Id == doc2.Id; };
          
        protected  System.Data.Linq.Table<Document> Documents
        {
            get { return _documents; }
            set { _documents = value; }
        }

        protected eQualDataContext  DataContext 
        {
            get { return  (eQualDataContext)Documents .Context ;} 
        }

        //internal to force factory use
        public DocumentDataAccesLayer()
        {
            Documents = provider.Documents;
        }

        #region IDocumentDataAccesLayer Members

        public IEnumerable <Document > GetDocuments()
        {
            var documents = from c in Documents
                            select c;

            return documents.ToList();
        }
        
        public void UpdateDocument(Document document)
        {  
            SubmitChanges();
        }

        public void DeleteDocument(Document document)
        {
            if (document == null) throw new Exception("document to be deleted is Null");

            var sameDocument = (from doc in Documents
                                where (doc.Id == document.Id)
                                select doc).ToList();

            if (sameDocument.Count == 0) throw new Exception("Looks like there is no such document in database");
 
            Documents.DeleteOnSubmit(document);
            SubmitChanges();
        }

        /// <summary>
        /// Add new Document in Database 
        /// </summary>
        /// <param name="document"></param>
        public void AddNewDocument(Document document)
        {
            if (document ==null || !(document is Document)) throw new Exception ("document Added is Null");

            var sameDocument = (from doc in provider.Documents
                               where (doc.Id == document.Id)
                               select doc).ToList();

            if(sameDocument.Count >0) throw new Exception("A document with same id is already in database ");

            Documents.InsertOnSubmit(document);
            SubmitChanges();
        }

        public void SubmitChanges()
        {
            Documents.Context.SubmitChanges();
        }     

        public IEnumerable<Document> GetDocumentsEmployeeNotified(string employeeId)
        {
            int empId = -1;
            int.TryParse(employeeId, out empId);

            if (empId > 0)
            {
                var notifidedDocuments =
                    from d in provider.Documents
                    from d_e in provider.Document_To_Employees
                    from e in provider.Employees
                    where e.id == empId 
                    where d.Id == d_e.id_document
                    where d_e.id_Employee == e.id
                    select d;

                return notifidedDocuments.ToList<Document>();
            }
            return null;
        }

        #endregion

        public IEnumerable<Employee> GetPersonApprovedDocument(int docId)
        {

            var employeesApprovedDoc =
                from d in DataContext.Documents
                from ap in DataContext.ApprovedBies
                from e in provider.Employees
                where e.id == ap.id_Employee
                where d.Id == ap.id_document
                where d.Id == docId
                select e;

            return employeesApprovedDoc.ToList<Employee>();

        }

        public IEnumerable<Document_Version> GetDocumentVersions(int docId)
        {
            var documentsVerions =
            from d in DataContext.Documents
            from v in DataContext.Document_Versions
            where d.Id == docId
            where d.Id == v.VersionId
            select v;

            return documentsVerions.ToList();
        }

        public IEnumerable<Form > GetFormsAndRecords()
        {
            return this.DataContext.Forms .ToList();
        }

        public IEnumerable<Form > GetDocumentFormsAndRecords(int docId)
        {
            //two line //
            Document doc = DataContext.Documents.SingleOrDefault(d => d.Id == docId);
            if (doc != null) return doc.Forms .ToList();

            // six lines //
            var documentsFormsAndRecords =
            from d in DataContext.Documents
            from f in DataContext.Forms
            where d.Id == docId
            where d.Id  == f.DocumentId 
            select f;

            return documentsFormsAndRecords.ToList();
        }

        public IEnumerable<DocumentType> GetDocumentTypes()
        {
            return DataContext.DocumentTypes.ToList();
        }

        public void AddNewDocumentVersion(Document_Version  p , Document oldDocument)
        {
            Document newDocument = new Document();

            newDocument.Title = oldDocument.Title;


        }

        public void AddNewFromRecord(Form  form_Record)
        {
            try
            {
                DataContext.Forms.InsertOnSubmit(form_Record);

                DataContext.SubmitChanges();
            }
            catch { throw new Exception("Cannot Add this Form record to database "); }

        }

        public void AddNewFromRecordToDocument(Form  form_Record, Document document)
        {
            eQualDataContext context = new eQualDataContext();
            try
            {  

                object form = document.Forms.SingleOrDefault(f => f.FormId == form_Record.FormId);
                if (document.Forms.SingleOrDefault(f => f.FormId == form_Record.FormId) != null) return;

                document.Forms.Add(form_Record);

                context.SubmitChanges();      
            }
            catch(Exception e) { throw new Exception("Cannot Add this Form record to database ",e); }
        }

        public bool DoesDocumentExist(Document document)
        {
            return DataContext.Documents.SingleOrDefault(p => p.Id == document.Id) != null;
        }

        public void RemoveFromRecordToDocument(Document document, System.Collections.IList iList)
        {
            foreach (Form  form in iList)
                RemoveFromRecordToDocument(document ,form);
        }

        private void RemoveFromRecordToDocument(Document document, Form  form)
        {
            if (document.Forms.Contains(form))
            {
                document.Forms.Remove(form);
                DataContext.SubmitChanges();
            }


        }

        public void AddAttachmentToDocument(Document doc, Attachment attachment)
        {
            doc.Attachment1 = attachment;
            DataContext.SubmitChanges();
        }

        public void UpdateDocuments()
        {

        }

        public void AddNewDocumentVersion(object ActiveItem, object version)
        {
            throw new NotImplementedException();
        }

        public IEnumerable<Form > GetDocumentFormsAndRecords()
        {
            return this.DataContext.Forms.ToList();
        }
    }
}
